package com.qsxc.dao.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.qsxc.business.bean.R;
import com.qsxc.business.promoter.bean.req.BindWechatUserReq;
import com.qsxc.business.promoter.bean.req.UnBindWechatUserReq;
import com.qsxc.business.promoter.bean.vo.PromoterFundsInfoVo;
import com.qsxc.business.promoter.bean.vo.PromoterUserInfoVo;
import com.qsxc.business.promoter.bean.vo.PromoterUserVo;
import com.qsxc.constants.Constants;
import com.qsxc.dao.entity.SmCheckcode;
import com.qsxc.dao.entity.SmPromoter;
import com.qsxc.dao.mapper.SmCheckcodeMapper;
import com.qsxc.dao.mapper.SmPromoterCashRecordMapper;
import com.qsxc.dao.mapper.SmPromoterDivideRecordMapper;
import com.qsxc.dao.mapper.SmPromoterMapper;
import com.qsxc.dao.service.ISmPromoterService;
import com.qsxc.utils.OSSClientUtil;
import com.qsxc.utils.RedisUtil;
import com.qsxc.utils.WeChatUtil;
import com.qsxc.utils.redisLock.RedisService;
import com.qsxc.utils.validator.Assert;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 推广员信息表 服务实现类
 * </p>
 *
 * @author
 * @since 2024-09-25
 */
@Slf4j
@Service
public class SmPromoterServiceImpl extends ServiceImpl<SmPromoterMapper, SmPromoter> implements ISmPromoterService {
    @Value("${wx.promoter.appid}")
    private String promoterAppid;
    @Value("${wx.promoter.appsecret}")
    private String promoterAppSecret;

    @Resource
    private SmPromoterMapper smPromoterMapper;
    @Resource
    private SmCheckcodeMapper smCheckcodeMapper;
    @Resource
    private SmPromoterDivideRecordMapper smPromoterDivideRecordMapper;
    @Resource
    private SmPromoterCashRecordMapper smPromoterCashRecordMapper;

    @Resource
    private RedisService redisService;

    @Override
    public R<String> sendRedirect(String code, String callBackJson, String url, HttpServletResponse response) throws Exception {
        log.info("sendRedirect ---> code：{}，callBackJson：{}，url：{}", code, callBackJson, url);

        String promoterRedirectUrlKey = "promoterRedirectUrl-" + code;
        if (RedisUtil.hasKey(promoterRedirectUrlKey)) {
            response.sendRedirect(RedisUtil.get(promoterRedirectUrlKey));
            return R.success(RedisUtil.get(promoterRedirectUrlKey));
        }

        JSONObject json = null;
        if (StringUtil.isNotBlank(callBackJson)) {
            json = JSONObject.parseObject(callBackJson);
        }

        String redirectUrl = null;
        if (json != null) {
            redirectUrl = json.getString("url");
        } else {
            redirectUrl = url;
        }

        String promoterWechatUserLockKey = "promoterWechatUserLock-" + code;
        redisService.getlock(promoterWechatUserLockKey);

        // 如果缓存中有，直接从缓存中读取
        String promoterWechatOpenidKey = "promoterWechatOpenid-" + code;
        Object redisOpenId = RedisUtil.get(promoterWechatOpenidKey);

        String openid = null;
        if (redisOpenId != null) {
            openid = String.valueOf(redisOpenId);
        } else {
            openid = WeChatUtil.getOpenId(code, promoterAppid, promoterAppSecret);
            if (StringUtil.isNotBlank(openid)) {
                RedisUtil.set(promoterWechatOpenidKey, openid, 300L);
            }
        }

        log.info("getWechatOpenid ---> param = code:{},appId:{}", code, promoterAppid);
        if (StringUtil.isNotBlank(openid)) {
            // Cookie cookie = new Cookie("openid", openid);
            // // 设置域名后可以解决重定向cookie丢失的问题
            // cookie.setDomain("qdrest.duolunxc.com");
            // cookie.setPath("/qdjx");
            // response.addCookie(cookie);
        }

        // 说明：跳转的url地址里已经存在请求参数
        if (redirectUrl.contains("?")) {
            redirectUrl = redirectUrl + "&openid=" + openid;
        } else {
            redirectUrl = redirectUrl + "?openid=" + openid;
        }

        if (json != null) {
            StringBuilder tempStr = new StringBuilder();
            tempStr.append("&");

            String hash = null;
            final String constantsHash = "hash";
            if (json.get(constantsHash) != null) {
                hash = json.getString(constantsHash);
                json.remove(constantsHash);
            }

            for (Object key : json.keySet()) {
                String keyStr = String.valueOf(key);
                if (!"url".equals(keyStr)) {
                    String value = json.getString(keyStr);
                    tempStr.append(keyStr).append("=").append(value).append("&");
                }
            }

            redirectUrl = redirectUrl + tempStr;
            if (StringUtils.isNotEmpty(hash)) {
                String[] strings = StringUtils.split(redirectUrl, "?");
                redirectUrl = strings[0] + "#/" + hash + "?" + strings[1];
            }
        }

        if (redirectUrl.substring(redirectUrl.length() - 1).equals("&")) {
            redirectUrl = redirectUrl.substring(0, redirectUrl.length() - 1);
        }

        log.info("redirect_url={}", redirectUrl);
        response.sendRedirect(redirectUrl);
        redisService.releaseLockWithDelay(promoterWechatUserLockKey, 0);
        RedisUtil.set(promoterRedirectUrlKey, redirectUrl, 300);
        return R.success(redirectUrl);
    }

    @Override
    public R bindWechatUser(BindWechatUserReq bindWechatUserReq) throws Exception {
        String openid = bindWechatUserReq.getOpenid();
        String telphoneCode = bindWechatUserReq.getTelphoneCode();

        // 根据openid查询推广员信息
        SmPromoter smPromoter = smPromoterMapper.queryByOpenid(openid);
        if (smPromoter != null) {
            return R.fail("该微信已绑定推广员");
        }

        // 根据手机号查询推广员信息
        smPromoter = smPromoterMapper.queryByTelephone(telphoneCode);
        Assert.isNull(smPromoter, "推广员信息不存在");

        SmCheckcode smCheckcode = smCheckcodeMapper.queryLastByPhoneNo(telphoneCode);
        Assert.isNull(smCheckcode, "验证码无效");
        Assert.isNotEquals(!bindWechatUserReq.getCheckCode().equals(smCheckcode.getCheckCode()), "验证码错误");
        smCheckcode.setIsUse("1");
        smCheckcodeMapper.updateById(smCheckcode);

        smPromoter.setOpenid(openid);
        smPromoter.setUpdateBy(Constants.DEFAULT_CREATED_BY);
        smPromoter.setUpdateTime(new Date());
        smPromoterMapper.updateById(smPromoter);
        return R.success();
    }

    @Override
    public R unBindWechatUser(UnBindWechatUserReq unBindWechatUserReq) throws Exception {
        String openid = unBindWechatUserReq.getOpenid();

        // 根据openid查询推广员信息
        SmPromoter smPromoter = smPromoterMapper.queryByOpenid(openid);
        if (smPromoter != null) {
            smPromoter.setOpenid(null);
            smPromoter.setUpdateBy(Constants.DEFAULT_CREATED_BY);
            smPromoter.setUpdateTime(new Date());
            smPromoterMapper.updateByIdWithNull(smPromoter);
        }
        return R.success();
    }

    @Override
    public R<PromoterUserInfoVo> getWechatUserInfo(String openid) throws Exception {
        // 根据openid查询推广员信息
        SmPromoter smPromoter = smPromoterMapper.queryByOpenid(openid);
        if (smPromoter != null) {
            // 获取推广员用户
            PromoterUserVo userInfo = getPromoterUserVo(smPromoter);

            PromoterUserVo higherUserInfo = null;
            // 查询上级推广员信息
            SmPromoter higherSmPromoter = smPromoterMapper.queryById(String.valueOf(smPromoter.getPId()));
            if (higherSmPromoter != null) {
                higherUserInfo = getPromoterUserVo(higherSmPromoter);
            }

            PromoterUserVo lowerUserInfo = null;
            List<PromoterUserVo> lowerUserInfoList = new ArrayList<>();
            // 查询下级推广员信息
            List<SmPromoter> lowerSmPromoterList = smPromoterMapper.queryListByPId(smPromoter.getId());
            for (SmPromoter lowerSmPromoter : lowerSmPromoterList) {
                lowerUserInfo = getPromoterUserVo(lowerSmPromoter);
                lowerUserInfoList.add(lowerUserInfo);
            }

            PromoterUserInfoVo promoterUserInfoVo = new PromoterUserInfoVo();
            promoterUserInfoVo.setUserInfo(userInfo);
            promoterUserInfoVo.setHigherUserInfo(higherUserInfo);
            promoterUserInfoVo.setLowerUserInfoList(lowerUserInfoList);

            return R.success(promoterUserInfoVo);
        }
        return R.success();
    }

    @Override
    public R<PromoterFundsInfoVo> getFundsInfo(String openid) throws Exception {
        // 根据openid查询推广员信息
        SmPromoter smPromoter = smPromoterMapper.queryByOpenid(openid);
        if (smPromoter == null) {
            return R.fail("推广员信息不存在");
        }

        Long promoterId = smPromoter.getId();
        // 总分成金额
        Double totalFunds = smPromoterDivideRecordMapper.getTotalDivideFunds(promoterId);
        // 已提现金额
        Double withdrawanFunds = smPromoterCashRecordMapper.getTotalCashFunds(promoterId, "2");
        // 审核金额
        Double reviewFunds = smPromoterCashRecordMapper.getTotalCashFunds(promoterId, "1");
        Double availWithdrawnFunds = totalFunds - withdrawanFunds - reviewFunds;

        PromoterFundsInfoVo promoterFundsInfoVo = new PromoterFundsInfoVo();
        promoterFundsInfoVo.setTotalFunds(totalFunds);
        promoterFundsInfoVo.setWithdrawnFunds(withdrawanFunds);
        promoterFundsInfoVo.setReviewFunds(reviewFunds);
        promoterFundsInfoVo.setAvailWithdrawnFunds(availWithdrawnFunds);

        return R.success(promoterFundsInfoVo);
    }

    private PromoterUserVo getPromoterUserVo(SmPromoter smPromoter) {
        PromoterUserVo promoterUserVo = new PromoterUserVo();
        promoterUserVo.setId(smPromoter.getId());
        promoterUserVo.setPromoterName(smPromoter.getName());
        promoterUserVo.setTelephone(smPromoter.getTelephone());

        String headUrl = smPromoter.getHeadUrl();
        if (StringUtil.isNotBlank(headUrl)) {
            promoterUserVo.setHeadUrl(OSSClientUtil.getBaseUrl(headUrl));
        }
        promoterUserVo.setBankCardNo(smPromoter.getBankCardNo());

        return promoterUserVo;
    }
}
